package main

import (
	"context"
	"fmt"
	"log"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// var Mong
func main() {
	Connect()

	client := MongoClient
	var ctx = context.TODO()
	databases, err := client.ListDatabaseNames(ctx, bson.M{})
	if nil != err {
		log.Fatal(err)
	}
	fmt.Println("databases: ", databases)

	db := client.Database("mytest")
	collectionName, err := db.ListCollectionNames(ctx, bson.M{})
	if nil != err {
		fmt.Println("Mongo list the Collection error:", err)
		return
	}

	fmt.Println("collectionName", collectionName)

	collection := db.Collection("study")
	fmt.Println("the collection name is ", collection.Name())

	// 插入数据
	// err = InsertsData(ctx)
	// if nil != err {
	// 	return
	// }

	// 查看数据
	// err = FindOne(ctx)
	err = FindMang(ctx)
	if nil != err {
		fmt.Println("Find error: ", err)
		return
	}

	// 更新的步骤
	// err = UpdateMang(ctx)
	// if nil != err {
	// 	fmt.Println("Update error: ", err)
	// 	return
	// }

	err = TransactionSC(ctx)
	if nil != err { // 正确来说应该是checkerr
		fmt.Println("事务执行完毕")
		return
	}

	// 查看索引
	// indexCursor, err := collection.Indexes().List(ctx)
	// var indexes []bson.M
	// if err = indexCursor.All(ctx, &indexes); err != nil {
	// 	log.Fatal(err)
	// }
}

// 插入数据
func InsertsData(ctx context.Context) error {
	stuCollection := MongoClient.Database("mytest").Collection("study")
	docs := []interface{}{
		bson.M{"name": "test1", "age": 1},
		bson.M{"name": "test2", "age": 33},
		bson.M{"name": "test3", "age": 2},
	}

	insertMangOps := options.InsertMany().SetOrdered(false)

	insertResult, err := stuCollection.InsertMany(ctx, docs, insertMangOps)
	if nil != err {
		fmt.Println("fail insert . error:", err)
		return err
	}
	fmt.Println("success insert the data :", insertResult.InsertedIDs)
	return nil
}

func checkErr(err error) bool {
	return true
}

func FindOne(ctx context.Context) error {
	var result User

	stuCollection := MongoClient.Database("mytest").Collection("study")

	findOneOps := options.FindOne() //.SetSort(nil).SetProjection

	singRes := stuCollection.FindOne(ctx, bson.M{}, findOneOps)

	if err := singRes.Decode(&result); err != nil {
		return err
	}
	fmt.Println(result)
	return nil
}
func FindMang(ctx context.Context) error {
	var result []*User

	stuCollection := MongoClient.Database("mytest").Collection("study")

	findOneOps := options.Find() //.SetSort(nil).SetProjection

	returnRes, err := stuCollection.Find(ctx, bson.M{}, findOneOps)
	if nil != err {
		fmt.Println("find error :", err)
		return err
	}

	if err := returnRes.All(ctx, &result); err != nil {
		return err
	}
	// fmt.Println(result)
	for _, res := range result {
		fmt.Println(res)
	}
	return nil
}

// 更新
func UpdateMang(ctx context.Context) error {

	stuCollection := MongoClient.Database("mytest").Collection("study")

	updateFilter := bson.M{"age": bson.M{"$gt": 1}}
	updateSet := bson.M{"$set": bson.M{"age": 11}}

	updateRes, err := stuCollection.UpdateMany(ctx, updateFilter, updateSet)
	if nil != err {
		fmt.Println("update error: ", err)
		return err
	}

	fmt.Println(
		updateRes.MatchedCount,
		updateRes.ModifiedCount,
		updateRes.UpsertedCount,
		updateRes.UpsertedID,
	)
	return nil
}

// 批量操作
func Bulk(ctx context.Context) error {

	collection := MongoClient.Database("mytest").Collection("study")

	// BulkWrite
	names := []string{"5t5", "娜娜明", "小黑", "蔷薇", "虎子"}
	models := []mongo.WriteModel{}                                 // 需要在这里定义动作的model
	updateOperation := bson.M{"$set": bson.M{"Animation": "咒术回战"}} // 更新动作为将Animation的值设置为咒术会战
	for _, name := range names {
		// 表示将所有name==上述的数组的按照更新动作opration处理
		// 此处没有特别定义一个filter
		updateOneModel := mongo.NewUpdateOneModel().SetFilter(bson.M{"name": name}).SetUpdate(updateOperation).SetUpsert(true)
		models = append(models, updateOneModel)
	} // 定义好批量操作的动作slice

	bulkWriteOpts := options.BulkWrite().SetOrdered(false)                    // 定义批量操作的options
	bulkWriteResults, err := collection.BulkWrite(ctx, models, bulkWriteOpts) // 执行批量操作
	if err != nil {
		log.Fatal(err)
	}

	// 结果基本和更新的结果一样
	fmt.Printf(
		"matched: %d  modified: %d  upserted: %d  upsertedIDs: %v\n",
		bulkWriteResults.MatchedCount,
		bulkWriteResults.ModifiedCount,
		bulkWriteResults.UpsertedCount,
		bulkWriteResults.UpsertedIDs,
	)
	return nil
}
